<?php

namespace App\Services;

use DB;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;

class PaymentService
{
    private $app;
    private $jssdk;

    public function __construct(){
        $config = config('wechat.payment.default');
        $this->app = Factory::payment($config);
    }

    public $msg = '支付出错';

    /**
     * 结算
     */
    public function settlement($uid, $time){
        //检查未结算成功的订单状态
        $data = \DB::table('settlement_order')->where([
            ['uid', $uid],
        ])->whereIn('status', [0, 1])->select(['transaction_no', 'id', 'status'])->get()->toArray();
        if( count($data) ){
            foreach ($data as $key => $value) {
                $message = $this->app->order->queryByOutTradeNumber($value->transaction_no);
                if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                    // 用户是否支付成功
                    if ( isset($message['trade_state']) && $message['trade_state'] === 'SUCCESS') {
                        $re = $this->settleResult($message['out_trade_no'], 1, $message['transaction_id']);
                    } else{
                        // 用户支付失败
                        $re = $this->settleResult($message['out_trade_no'], 0, "");
                    }
                }
            }
        }


        $openid = DB::table('users')->where('id', $uid)->value('openid');
        if( !$openid ) return false;
        $list = DB::table('users_orders')->where([
            ['store_uid', $uid],
            ['created_at', '<', date('Y-m-d H:i:s', $time)],
            ['settlement_id', 0],
        ])->whereIn('status', [35,40])->select(['id', 'real_return_money', 'settle_amount'])->get()->toArray();
        if( !count($list) ){
            $this->msg = '暂无需要结算的订单';
            return false;
        }

        $amount = 0;
        $ids = [];
        foreach ($list as $item) {
            $amount += $item->settle_amount;
            $ids[] = $item->id;
        }
        if( $amount && count($ids) ){
            $out_trade_no = getOrderNo($uid, 2);
            $payData = [
                'body' => '商户结算',
                'out_trade_no' => $out_trade_no,
                'total_fee' => $amount*100,
                'notify_url' => config('app.callback_URL').'/api/settle/callback', // 支付结果通知网址
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $openid,
            ];
            try {
                DB::beginTransaction();
                $settlement_id = DB::table('settlement_order')->insertGetId([
                    'uid'   => $uid,
                    'amount'   => $amount,
                    'transaction_no'   => $out_trade_no,
                    'text'   => json_encode($payData),
                    'status'   => 1,
                    'created_at'    => date('Y-m-d H:i:s'),
                ]);
                DB::table('users_orders')->whereIn('id', $ids)->update(['settlement_id'=>$settlement_id, 'updated_at'=>date('Y-m-d H:i:s')]);
                $result = $this->app->order->unify($payData);
                if( $result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS' ){
                    throw new \Exception('获取支付信息异常');
                }

                $jssdk =  $this->app->jssdk;
                $config = $jssdk->bridgeConfig($result['prepay_id'], false);
                DB::commit();
                return $config;
            }catch (\Exception $exception){
                DB::rollBack();
                $this->msg = $exception->getMessage();
            }

        }else{
            $this->msg = '结算金额有误';
        }

        return false;

    }
    /**
     * 开通vip
     */
    public function openVip($uid){
        $user = DB::table('users')->where('id', $uid)->first();
        if( !$user ) return false;
        $openid = $user->openid;
        
        $out_trade_no = getOrderNo($uid, 3);
        $payData = [
            'body' => 'Plus会员月卡',
            'out_trade_no' => $out_trade_no,
            'total_fee' => config('app.vip_amount')*100,
            'notify_url' => config('app.callback_URL').'/api/vip/callback', // 支付结果通知网址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $openid,
        ];


        try {
            DB::beginTransaction();
            \DB::table('users_vip_receive_log')->insert([
                'type'  => 4,
                'uid'  => $uid,
                'num'   => config('app.vip_day_num'),
                'transaction_no'   => $out_trade_no,
                'amount'   => config('app.vip_amount'),
                'status'   => 1,
                'text'   => json_encode($payData),
                'created_at'   => getDt(),
                'updated_at'   => getDt(),
            ]);
            if( $user->is_debug == 1 ) $payData['total_fee'] = 1;
            $result = $this->app->order->unify($payData);
            if( $result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS' ){
                throw new \Exception('获取支付信息异常');
            }
            
            // var_dump($result['prepay_id']);exit;
            $jssdk =  $this->app->jssdk;
            $config = $jssdk->bridgeConfig($result['prepay_id'], false);
            DB::commit();
            return $config;
        } catch (\Exception $e) {
            DB::rollBack();
            $this->msg = $e->getMessage();
            return false;
        }

    }
    /**
     * 提现
     */
    public function withdrawal($uid, $amount): bool
    {
        $user = DB::table('users')->where('id', $uid)->first();
        if( !$user ){
            $this->msg = '用户有误';
            return false;
        }

        if( $amount < 15 ){
            $this->msg = '满15返现金可兑换';
            return false;
        }

        if( $amount > $user->balance ){
            $this->msg = '兑换失败，品鉴金不足';
            return false;
        }
        if( DB::table('users_withdrawal')->where('uid', $uid)->whereIn('status', [1,4])->count() ){
            $this->msg = '您还有未提现成功的记录，无法重复提交申请';
            return false;
        }
        $out_trade_no = getOrderNo($uid, 6);
        $payData = [
            'partner_trade_no' => $out_trade_no, // 商户订单号，需保持唯一性(只能是字母或者数字，不能包含有符号)
            'openid' => $user->openid,
            'check_name' => 'NO_CHECK', // NO_CHECK：不校验真实姓名, FORCE_CHECK：强校验真实姓名
            'amount' => ($amount - getWithdrawalFee($amount))*100, // 企业付款金额，单位为分
            'desc' => '兑换品鉴金', // 企业付款操作说明信息。必填
        ];
        
        try {
            DB::beginTransaction();

            //添加提现记录
            $id = DB::table('users_withdrawal')->insertGetId([
               'uid'    => $uid,
               'money'    => $amount,
               'status'    => 1,
               'transaction_no'    => $out_trade_no,
               'text'    => json_encode($payData),
               'created_at'    => getDt(),
            ]);
            //余额变动
            UserService::userBalanceUpdate($uid, -$amount, 0, $id, 1, $out_trade_no);

            //提现申请
            if( $user->is_debug == 1 ) $payData['amount'] = 30;//测试账号提现0.3元
            $result = $this->app->transfer->toBalance($payData);
            //    var_dump($result);exit;
           //严格判断是否请求成功,模糊的以回调或订单查询结果为准
           if( $result['return_code'] == 'FAIL' ){
               //通信失败
               throw new \Exception('兑换申请失败');
           }elseif( $result['result_code'] == 'SUCCESS' ){
                //更新订单
                DB::table('users_withdrawal')->where('transaction_no', $out_trade_no)->update(['status'=>2, 'updated_at'=>getDt(), 'wx_no'=>$result['payment_no']]);
                $da = ['type'=>6, 'type_value'=>'兑现服务费', 'title'=>'用户兑现', 'order_no'=>getOrderNo($uid, 5), 'transaction_no'=>$out_trade_no, 'amount'=>getWithdrawalFee($amount), 'created_at'=>getDt()];
                //平台对账明细添加
                \DB::table('platform_balance_log')->insert($da);
           }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            $this->msg = $e->getMessage();
            return false;
        }

    }

    /**
     * 开通vip结果业务处理
     * @param string $transactionNo 支付流水号
     * @param int $status 支付流水号 1-成功，0-失败
     * @param string $wxNo 微信流水号
     */
    public function openVipResult(string $transactionNo,int $status, string $wxNo): bool
    {
        $order = DB::table('users_vip_receive_log')->where('transaction_no', $transactionNo)->first();
        if( !$order ){
            return false;
        }
        if( $order->status != 1 ){
            //防止重复回调
            return true;
        }
        try {
            DB::beginTransaction();
            if( $status == 1 ){
                //更新订单
                DB::table('users_vip_receive_log')->where('transaction_no', $transactionNo)->update(['status'=>2, 'updated_at'=>getDt(), 'wx_no'=>$wxNo]);
                //平台对账明细添加
                $data = [
                    ['type'=>7, 'type_value'=>'会费入账', 'title'=>'Plus会员月卡', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>$order->amount, 'created_at'=>getDt()],
                    ['type'=>2, 'type_value'=>'交易手续费', 'title'=>'Plus会员月卡', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>getWxFee($order->amount), 'created_at'=>getDt()],
                ];
                DB::table('platform_balance_log')->insert($data);

                $user = \Illuminate\Support\Facades\DB::table('users')->where('id', $order->uid)->select(['vip_status', 'vip_overdue'])->first();
                if( $user->vip_status == 1 ){
                    DB::table('users')->where('id', $order->uid)->update(['vip_overdue'=>date('Y-m-d H:i:s', strtotime('+'.$order->num.' day', strtotime($user->vip_overdue))), 'updated_at'=>getDt(), 'vip_status'=>1]);
                }else{
                    DB::table('users')->where('id', $order->uid)->update(['vip_overdue'=>date('Y-m-d H:i:s', strtotime('+'.$order->num.' day', time())), 'updated_at'=>getDt(), 'vip_status'=>1]);
                }

            }else{
                //更新vip订单状态
                DB::table('users_vip_receive_log')->where('transaction_no', $transactionNo)->update(['status'=>3, 'updated_at'=>getDt()]);
            }

            DB::commit();
            return true;
        }catch (\Exception $exception){
            DB::rollBack();
            return false;
        }


    }

    /**
     * 结算回调业务
     * @param string $transactionNo
     * @param int $status
     * @param string $wxNo
     * @return bool
     */
    public function settleResult(string $transactionNo,int $status, string $wxNo):bool
    {
        $order = DB::table('settlement_order')->where('transaction_no', $transactionNo)->first();
        $merchantUser = DB::table('users')->where('id', $order->uid)->first();
        if( !$order || !$merchantUser ){
            return false;
        }
        if( $order->status != 1 ){
            //防止重复回调
            return true;
        }
        $list = DB::table('users_orders')->where([
            ['store_uid', $order->uid],
            ['settlement_id', $order->id],
        ])->whereIn('status', [35,40])->select(['id', 'uid', 'real_return_money', 'store_title', 'good_comment_type', 'max_money', 'return_money'])->get()->toArray();
        if( !count($list) ){
            return false;
        }

        try {
            DB::beginTransaction();
            if( $status == 1 ){
                //更新订单
                DB::table('settlement_order')->where('transaction_no', $transactionNo)->update(['status'=>2, 'updated_at'=>getDt(), 'wx_no'=>$wxNo]);
                //修改订单状态
                DB::table('users_orders')->where([
                    ['store_uid', $order->uid],
                    ['settlement_id', $order->id],
                ])->whereIn('status', [35,40])->update(['status'=>50, 'updated_at'=>getDt()]);

                //平台对账信息数组
                $data = [
                    ['type'=>1, 'type_value'=>'订单结算', 'title'=>'商家结算', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>$order->amount, 'created_at'=>getDt()],
                    ['type'=>2, 'type_value'=>'交易手续费', 'title'=>'商家结算', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>getWxFee($order->amount), 'created_at'=>getDt()],
                ];
                foreach ($list as $item) {

                    //给订单用户返佣品鉴金
                    $user = DB::table('users')->where('id', $item->uid)->first();
                    if( $user ){
                        $data[] = ['type'=>3, 'type_value'=>'订单返佣', 'title'=>$item->store_title."<br>".($item->good_comment_type?config('app.good_comment_type')[$item->good_comment_type]:'')."满{$item->max_money}返{$item->return_money}", 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>$item->real_return_money, 'created_at'=>getDt()];
                        UserService::userBalanceUpdate($item->uid, $item->real_return_money, 1, $item->id, 1, $transactionNo);
                        if( $user->pid && DB::table('users')->where('id', $user->pid)->count() ){
                            //上级返佣
                            // $data[] = ['type'=>4, 'type_value'=>'好友返佣', 'title'=>$item->store_title."<br>".($item->good_comment_type?config('app.good_comment_type')[$item->good_comment_type]:'')."满{$item->max_money}返{$item->return_money}", 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>config('app.parent_amount'), 'created_at'=>getDt()];
                            UserService::userBalanceUpdate($user->pid, config('app.parent_amount'), 2, $item->id, 0, $transactionNo);
                        }
                    }
                }

                //平台对账明细添加
                DB::table('platform_balance_log')->insert($data);

                //如果冻结，检查是否结算完毕，恢复正常状态
                $count = \DB::table('users_orders')->where('store_uid', $order->uid)->whereIn('status', [40,35])->where('created_at', '<', date('Y-m-d 00:00:00', strtotime('-1 day', time())))->count();
                if( !$count && $merchantUser->frozen_date != null ){
                    //已冻结，但是当前无待结算订单，可恢复
                    \DB::table('users')->where('id', $order->uid)->update(['frozen_date'=>null, 'created_at'=>getDt()]);
                    \DB::table('subsidy')->where('uid', $order->uid)->update(['is_frozen'=>0, 'created_at'=>getDt()]);
                }

            }else{
                //更新vip订单状态
                DB::table('settlement_order')->where('transaction_no', $transactionNo)->update(['status'=>3, 'updated_at'=>getDt()]);
                DB::table('users_orders')->where([
                    ['store_uid', $order->uid],
                    ['settlement_id', $order->id],
                ])->whereIn('status', [35,40])->update(['status'=>40, 'updated_at'=>getDt(), 'settlement_id'=>0]);

            }

            DB::commit();
            return true;
        }catch (\Exception $exception){
            DB::rollBack();
            return false;
        }
    }

    /**
     * 提现回调业务
     * @param string $transactionNo
     * @param int $status
     * @param string $wxNo
     * @return bool
     */
    public function withdrawalResult(string $transactionNo,int $status, string $wxNo):bool
    {
        $order = DB::table('users_withdrawal')->where('transaction_no', $transactionNo)->first();
        if( !$order ){
            return false;
        }
        if( $order->status != 1 ){
            //防止重复回调
            return true;
        }

        try {
            DB::beginTransaction();
            if( $status == 1 ){
                //更新订单
                DB::table('users_withdrawal')->where('transaction_no', $transactionNo)->update(['status'=>2, 'updated_at'=>getDt(), 'wx_no'=>$wxNo]);
                $da = ['type'=>6, 'type_value'=>'兑现服务费', 'title'=>'用户兑现', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>getWithdrawalFee($order->money), 'created_at'=>getDt()];
                //平台对账明细添加
                \DB::table('platform_balance_log')->insert($da);
            }else{
                //更新vip订单状态
                DB::table('users_withdrawal')->where('transaction_no', $transactionNo)->update(['status'=>3, 'updated_at'=>getDt()]);
                //退回用户余额
                UserService::userBalanceUpdate($order->uid, $order->money, 6, $order->id, 1, $transactionNo);
                // $da = ['type'=>10, 'type_value'=>'退回兑现服务费', 'title'=>'退回兑现服务费', 'order_no'=>getOrderNo($order->uid, 5), 'transaction_no'=>$transactionNo, 'amount'=>getWithdrawalFee($order->money), 'created_at'=>getDt()];
                // //平台对账明细添加
                // \DB::table('platform_balance_log')->insert($da);
            }

            DB::commit();
            return true;
        }catch (\Exception $exception){
            DB::rollBack();
            return false;
        }
    }


}